/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#ifndef __WOW_DBC_FILE_H__
#define __WOW_DBC_FILE_H__

#include "WOWDbc.h"
#include "MPQArchive.h"

namespace PQGameCore
{
	/*
	The DBC (DataBaseClient) files are clientside databases 
	containing data about Items, NPC's, Enviroment, World etc.
	*/
	class WOWDbcFile
	{
	private:
		std::string _fileName;
		int _fileSize;
		WOWDbcHeader *_header;
		unsigned char* _buf;
		unsigned char* _data;//ptr to buffer _data begin
		unsigned char* _strTable;
	public:
		~WOWDbcFile(void);
		WOWDbcFile(PQEngine::FileBase* file);

		void init();

		//get record _data ptr by index
		unsigned char* getRecordData(int index)
		{
			if(index>=_header->records||index<0){
				return 0;
			}
			int offset=index*_header->recordSize;
			return _data+offset;
		}

		//get integer field in record
		int getIntField(int recordIndex,int fieldIndex)
		{
			assert(recordIndex>=0);
			assert(recordIndex<_header->records);
			assert(fieldIndex>=0);
			assert(fieldIndex<_header->fields);

			int recordOffset=recordIndex*_header->recordSize;
			int fieldOffset=fieldIndex*4;

			return *(int*)(_data+recordOffset+fieldOffset);

		}

		Ogre::uint getUIntField(int recordIndex,int fieldIndex)
		{
			assert(recordIndex>=0);
			assert(recordIndex<_header->records);
			assert(fieldIndex>=0);
			assert(fieldIndex<_header->fields);

			int recordOffset=recordIndex*_header->recordSize;
			int fieldOffset=fieldIndex*4;

			return *(Ogre::uint*)(_data+recordOffset+fieldOffset);
		}

		float getFloatField(int recordIndex,int fieldIndex)
		{
			assert(recordIndex>=0);
			assert(recordIndex<_header->records);
			assert(fieldIndex>=0);
			assert(fieldIndex<_header->fields);

			int recordOffset=recordIndex*_header->recordSize;
			int fieldOffset=fieldIndex*4;

			return *(float*)(_data+recordOffset+fieldOffset);
		}

		char *getStringField(int recordIndex,int fieldIndex)
		{
			Ogre::uint offset = getUIntField(recordIndex,fieldIndex);
			assert(offset < _header->strBlockSize);
			return (char*)(_strTable + offset);
		}

		char *getStringField(int offset)
		{
			assert(offset < _header->strBlockSize);
			return (char*)(_strTable + offset);
		}

		char *getLocalizedStringField(int recordIndex,int fieldIndex, int locale = -1 )
		{
			int loc = locale;
			Ogre::uint offset =0;
			if( locale == -1 ){
				assert(fieldIndex < _header->fields -  8 );
				for( loc = 0; loc < 8; loc++ ){
					offset = getUIntField(recordIndex,fieldIndex + loc);
					if( offset != 0 )
						break;
				}
			}
			
			assert( fieldIndex + loc < _header->fields );
			offset = getUIntField(recordIndex,fieldIndex + loc );
			assert(offset < _header->strBlockSize );
			return (char*)(_strTable + offset);
		}

		inline int getRecordCount()
		{
			return _header->records;
		}

	};
}
#endif
